package com.seal.commons.config.apollo.spi;

import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.internals.LegacyMetaServerProvider;
import com.ctrip.framework.apollo.core.spi.MetaServerProvider;
import com.google.common.collect.Lists;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.SpringFactoriesLoader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.seal.commons.config.apollo.configuration.ApolloProperties.APOLLO_PROPERTIES_PREFIX;
import static com.seal.commons.config.apollo.configuration.ApolloProperties.META_SERVER_ADDR;

/**
 * ClassName:ApolloMetaServiceProvider <br/>
 * func:     apollp spi 实现
 * Date:     2019-05-17 11:23 <br/>
 *
 * @author yong.huang
 * @see
 * @since JDK 1.8
 */
public class ApolloMetaServiceProvider implements MetaServerProvider {

    public static final int ORDER = LegacyMetaServerProvider.ORDER + 1;

    private static final  Map<String, String> domains = new HashMap<>();

    private static final String DEFAULT_NAMES = "bootstrap.";

    public ApolloMetaServiceProvider(){
        initialize();
    }
    private void initialize() {
        List<PropertySourceLoader> propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());

        AnnotationAwareOrderComparator.sort(propertySourceLoaders);
        StandardEnvironment environment = new StandardEnvironment();
        MutablePropertySources mutablePropertySources = environment.getPropertySources();

        for (PropertySourceLoader propertySourceLoader : propertySourceLoaders) {
            String[] fileExtensions = propertySourceLoader.getFileExtensions();
            ArrayList<String> fileExtensionList = Lists.newArrayList(fileExtensions);
            for (String fileExtension : fileExtensionList) {
                ClassPathResource bootstrapResource = new ClassPathResource(DEFAULT_NAMES + fileExtension);
                List<PropertySource<?>> propertySources;
                try {
                    propertySources = propertySourceLoader.load(DEFAULT_NAMES + fileExtension, bootstrapResource);
                } catch (Exception e) {
                    // ignore
                    continue;
                }
                propertySources.forEach(mutablePropertySources::addFirst);
            }
        }
        Map<String, String> propMap = Binder.get(environment).bind(APOLLO_PROPERTIES_PREFIX + "." + META_SERVER_ADDR, Map.class).get();
        domains.putAll(propMap);
    }


    @Override
    public String getMetaServerAddress(Env env) {
        String metaServerAddress = domains.get(env.toString().toLowerCase());
        return metaServerAddress == null ? null : metaServerAddress.trim();
    }

    @Override
    public int getOrder() {
        return ORDER;
    }
}
